﻿#ifndef SLTOOL_MEMORY_20220124_
#define SLTOOL_MEMORY_20220124_
#include <stdlib.h>
#include <stdint.h>
#include <memory>
#include <atomic>
#include <mutex>
#include <string.h>
#ifdef WIN32
#else
#include <unistd.h>
#endif

#include "SLT_smartEmbedPtr.h"

class SLT_memData : public SLT_EmbedSptrCounterBase< SLT_memData>
{
public:
	static SLT_memData* newData(int _len) {
		char* pbuf = new(std::nothrow) char[sizeof(SLT_memData) + _len];
		if (pbuf) {
			return new(pbuf) SLT_memData(pbuf + sizeof(SLT_memData), _len);
		}
		return nullptr;
	}

private:
	SLT_memData(char* _p, int _len) :SLT_EmbedSptrCounterBase(SLT_memBufHead_deleter) {
		m_pbuf = _p; m_size = _len;
	}

	static void SLT_memBufHead_deleter(SLT_memData* _p)
	{
		_p->~SLT_memData();
		delete (char*)_p;
	}
	
	SLT_memData(SLT_memData& _data);
	SLT_memData& operator=(const SLT_memData& _data);

public:

	char* m_pbuf =nullptr;
	uint32_t  m_size = 0;
	uint32_t  m_len  = 0;
};
typedef SLT_EmbedSmartPtr< SLT_memData>  SLT_memDataSptr;

//内存空间
class SLT_memBuf
{
public:
	void clear() {
		m_len = 0;
	}
	void reset() {
		m_bufPtr.reset();
		m_size = 0;
		m_len = 0;
	}
	void add(const char* _pdata, uint32_t _len)
	{
		if (nullptr == _pdata || 0 == _len) {
			return;
		}
		if (m_len != 0) {
			if (_pdata == m_bufPtr->m_pbuf && _len == m_len) {
				return;
			}
		}
		SLT_memDataSptr newbufPtr(SLT_memData::newData(_len));
		if (newbufPtr) {
			memcpy(newbufPtr->m_pbuf, _pdata, _len);
			m_bufPtr = newbufPtr;
			m_size = _len;
			m_len = _len;
			return;
		}
		reset();
	}
	
	void resize(uint32_t _size) {
		m_len = 0;
		if (_size > 0) {
			if(_size == m_size){
				return;
			}
			m_bufPtr.reset(SLT_memData::newData(_size));
		}
		else {
			m_bufPtr.reset();
		}
				
		if (m_bufPtr) {
			m_size = _size;
		}
		else {
			m_size = 0;
		}
	}
	void append(const char* _pdata, uint32_t _len) {
		if (nullptr == _pdata || 0 == _len) {
			return;
		}
		if ((m_size - m_len) < _len) {
			int newsize = m_size * 2 + _len;
			SLT_memDataSptr newbuf(SLT_memData::newData(newsize));
			if (!newbuf) {
				m_bufPtr.reset(nullptr);
				m_len = 0;
				m_size = 0;
				return;
			}
			
			if (m_len > 0) {
				memcpy(newbuf->m_pbuf, m_bufPtr->m_pbuf, m_len);
			}
			m_bufPtr = newbuf;
			m_size = newsize;
		}
		memcpy(m_bufPtr->m_pbuf + m_len, _pdata, _len);
		m_len += _len;
	}
	void removeHead(uint32_t _len) {
		if (!m_bufPtr) {
			return;
		}
		if (0 == _len) {
			return;
		}
		if (_len >= m_len) {
			m_len = 0;
			return;
		}
		memmove(m_bufPtr->m_pbuf, m_bufPtr->m_pbuf + _len, m_len - _len);
		m_len = m_len - _len;
	}
	char* get() {
		//没有内容，则返回空
		if (m_len == 0) {
			return nullptr;
		}
		return m_bufPtr->m_pbuf;
	}
	char* bufAddr() {
		//直接返回缓存地址
		if (m_bufPtr) {
			return m_bufPtr->m_pbuf;
		}
		return nullptr;
	}
	uint32_t getLen() {
		return m_len;
	}
	uint32_t getSize() {
		return m_size;
	}


	//std::shared_ptr<char>  m_bufPtr2;
	//SLT_memBufHeadSptr  m_bufPtr{nullptr,SLT_memBufHead_deleter };
	SLT_memDataSptr  m_bufPtr;
	uint32_t  m_size = 0;
	uint32_t  m_len = 0;
};



/// <summary>
/// 内存检查
/// </summary>
struct SLT_memLeakObjInfo
{
	std::atomic<uint32_t>  m_count{0};
};
//依赖日志模块，必须在日志模块初始化后执行
SLT_API int SLT_memLeakInit(int _showtime_s,bool _show_0 = false);
SLT_API void SLT_memLeak_addobj(const char* pname, SLT_memLeakObjInfo *_pinfo);

template <class T>
class SLT_memLeakCheck
{
public:
	SLT_memLeakCheck() {
		std::call_once(of, [] {
			m_pobj = new SLT_memLeakObjInfo;
			SLT_memLeak_addobj(typeid (T).name(), m_pobj);
			});
		m_pobj->m_count++;
	}
	SLT_memLeakCheck(const SLT_memLeakCheck& _val) {
		std::call_once(of, [] {
			m_pobj = new SLT_memLeakObjInfo;
			SLT_memLeak_addobj(typeid (T).name(), m_pobj);
			});
		m_pobj->m_count++;
	}
	virtual ~SLT_memLeakCheck() {
		m_pobj->m_count--;
	}
private:
	static SLT_memLeakObjInfo* m_pobj;
	static std::once_flag of;
	
};
template <class T> SLT_memLeakObjInfo* SLT_memLeakCheck<T>::m_pobj = nullptr;
template <class T> std::once_flag SLT_memLeakCheck<T>::of;

#endif